package cn.gene.timeyan.security.sso.service.impl;

import cn.gene.timeyan.common.constant.RedisConstants;
import cn.gene.timeyan.common.exception.TimeyanServiceException;
import cn.gene.timeyan.common.exception.handler.UserException;
import cn.gene.timeyan.common.restful.JsonResult;
import cn.gene.timeyan.common.restful.ResponseCode;
import cn.gene.timeyan.common.utils.JwtTokenUtils;
import cn.gene.timeyan.common.utils.VerificationUtils;
import cn.gene.timeyan.pojo.ums.model.User;
import cn.gene.timeyan.pojo.valid.security.dto.UpdatePwdDTO;
import cn.gene.timeyan.pojo.valid.security.dto.UserCodeLoginDTO;
import cn.gene.timeyan.pojo.valid.security.dto.validateCodeDTO;
import cn.gene.timeyan.pojo.valid.security.model.UserLoginAccount;
import cn.gene.timeyan.pojo.valid.security.model.UserValidation;
import cn.gene.timeyan.security.sso.mapper.user.*;
import cn.gene.timeyan.security.sso.service.IUserValidationService;
import cn.gene.timeyan.security.sso.utils.EmailUtils;
import cn.gene.timeyan.security.sso.utils.LoginUtils;
import cn.gene.timeyan.security.sso.utils.UserUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 登录验证码服务类*
 *
 * @author LWG
 * @date 2022/8/1 21:39
 * @since 1.0.0 @gene.cn
 */

@Service
public class UserValidationServiceImpl extends ServiceImpl<UserValidationDao, UserValidation> implements IUserValidationService {
    @Autowired
    UserDao userDao;
    @Autowired
    UserLoginAccountDao loginAccountDao;
    @Autowired(required = false)
    UserLoginAccountMapper loginAccountMapper;
    @Autowired
    UserValidationDao validationDao;
    @Autowired
    UserUtil util;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private VerificationUtils verificationUtils;
    @Resource
    private EmailUtils emailUtils;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;

    @Override
    public User validateCode(validateCodeDTO validateCodeDTO) {
        QueryWrapper wrapper = new QueryWrapper();
        String stateOfLoginKey = "";
        String loginKey = validateCodeDTO.getLoginKey();
        //判断用户是否使用手机号登录
        if (util.isNumeric(loginKey)) {
            wrapper.eq("phone", validateCodeDTO.getLoginKey());
            stateOfLoginKey = "phone";
        } else {
            wrapper.eq("email", validateCodeDTO.getLoginKey());
            stateOfLoginKey = "email";
        }

        //获取登录账户id，通过该信息获取用户验证码账户id
        UserLoginAccount loginAccount = loginAccountDao.selectOne(wrapper);
        if (loginAccount == null) {
            throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "用户不存在");
        }

        Long loginAccountId = loginAccount.getId();
        wrapper.clear();
        wrapper.eq(loginAccountId != null, "login_account_id", loginAccountId);
        User user = userDao.selectOne(wrapper);

        //若用户注销或不存在
        if (user == null) {
            throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "用户不存在");
        }
        //获取验证码id后通过id查找账户并验证验证码
        UserValidation validation = validationDao.selectById(user.getUserId());
        //手机和邮箱验证码不存储在同一位置
        String backValidCode = "phone".equals(stateOfLoginKey) ? validation.getPhoneCode() : validation.getEmailCode();

        if (!validateCodeDTO.getCode().equals(backValidCode)) {
            throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "验证码错误");
        }

        return user;
    }

        /*@Override
        public void sendEmailForLogin(String email) {
            if (email.isEmpty()) {
                throw new UserException(States.ERR_USER_NOT_FOUND.getStates(), "邮箱不能为空");
            }
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("email", email);
            UserLoginAccount loginAccount = loginAccountDao.selectOne(wrapper);
            if (loginAccount == null) {
                throw new UserException(States.ERR_USER_NOT_FOUND.getStates(), "该邮箱尚未绑定");
            }
            wrapper.clear();
            wrapper.eq("login_account_id", loginAccount.getId());
            User user = userDao.selectOne(wrapper);

            //获取发送的验证码
            String code = util.sendValidEMail(email);
            validationDao.updateById(validationDao.selectById(user.getValidationId()).setEmailCode(code));

        }*/

    @Override
    public void sendSmsForLogin(String phone) {
        if (phone.isEmpty()) {
            throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "手机号不能为空");
        }
        if (!util.isNumeric(phone)) {
            throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "手机号格式不正确");
        }


//            QueryWrapper wrapper = new QueryWrapper();
//            wrapper.eq("phone", phone);
//            UserLoginAccount loginAccount = loginAccountDao.selectOne(wrapper);
            /*User loginAccount = loginAccountMapper.getByPhone(phone);
            if (loginAccount == null) {
                throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "该手机号尚未注册");
            }*/
//            wrapper.clear();
//            wrapper.eq("login_account_id", loginAccount.getId());
//            User user = userDao.selectOne(wrapper);
        /*User user = loginAccountMapper.getByUserId(loginAccount.getUserId());*/

        //获取发送的验证码
        String code = util.sendValidSms(phone);
        /*validationDao.updateById(validationDao.selectById(user.getUserId()).setPhoneCode(code));*/
    }

    @Override
    public JsonResult<String> sendCodeByPhone(String phone) {
        if (!verificationUtils.isPhone(phone)){
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"手机号格式不合法");
        }
        //获取发送的验证码
        String code = util.sendValidSms(phone);
        //存入缓存,保存30分钟
        redisTemplate.opsForValue().set(RedisConstants.VERIFY_CODE_KEY+phone,code,30, TimeUnit.MINUTES);
        return JsonResult.ok("发送成功");
    }
    @Override
    public JsonResult<String> sendCodeByEmail(String email) {
        if (!verificationUtils.isEmail(email)){
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"邮箱号格式不合法");
        }
        Random random = new Random();
        int i = random.nextInt() * 10000;
        //获取发送的验证码
        String code = String.valueOf(i).substring(1, 5);
        //发送邮件
        try{
            emailUtils.sendVerificationCode(email,code);
        }catch (Exception e) {
            //验证码发送失败抛出异常
            throw new TimeyanServiceException(ResponseCode.ERR_UNKNOWN,"啊哦，验证码发送失败，请重新发送");
        }
        //存入缓存,保存30分钟
        redisTemplate.opsForValue().set(RedisConstants.VERIFY_CODE_KEY+email,code,30, TimeUnit.MINUTES);
        return JsonResult.ok("发送成功");
    }
    @Override
    public JsonResult<String> checkCode(UserCodeLoginDTO userCodeLoginDTO) {
        String email=userCodeLoginDTO.getUsername();
        String code=userCodeLoginDTO.getCode();
        if (userCodeLoginDTO==null||email==null||code==null){
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"邮箱号或验证码不能为空");
        }
        if (!verificationUtils.isEmail(email)){
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"邮箱号格式不合法");
        }
        String cacheCode = redisTemplate.opsForValue().get(RedisConstants.VERIFY_CODE_KEY + email).toString();
        //是否过期
        if (cacheCode==null||cacheCode.isEmpty()){
            System.out.println("验证码已过期");
            throw new TimeyanServiceException(ResponseCode.ERR_VERIFICATION_CODE_VALUE,"验证码已过期，请重新发送");
        }
        //是否正确
        if (!cacheCode.equals(code)){
            System.out.println("验证码错误");
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"验证码输入错误");
        }

        return JsonResult.ok("验证成功");
    }

    @Override
    public JsonResult<String> updatepwd(UpdatePwdDTO updatePwdDTO, HttpServletRequest request) {
        if (updatePwdDTO==null){
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"新密码不能为空");
        }
        String newPwd=updatePwdDTO.getPwd();
        if (newPwd==null){
            throw new TimeyanServiceException(ResponseCode.ERR_BAD_REQUEST,"新密码不能为空");
        }
        String ip = LoginUtils.getIpAddress(request);
        String token = request.getHeader("token");
        if (token!=null){
            String username=jwtTokenUtils.getUserInfo(token).getUsername();
            int line=userMapper.updatePwd(username,updatePwdDTO.getPwd());
            if (line<1){
                throw new TimeyanServiceException(ResponseCode.ERR_UPDATE,"更改密码失败");
            }
            return JsonResult.ok("更改成功");
        }
        String username= updatePwdDTO.getUsername();
        String pwd=userMapper.getPwdByUserName(username);
        if (newPwd.equals(pwd)){
            throw new TimeyanServiceException(ResponseCode.ERR_UPDATE,"请勿使用旧密码");
        }
        if (username!=null){
            int line=userMapper.updatePwd(username,updatePwdDTO.getPwd());
            if (line<1){
                throw new TimeyanServiceException(ResponseCode.ERR_UPDATE,"更改密码失败,请确保您的用户名无误");
            }
            return JsonResult.ok("更改成功");
        }
        throw new TimeyanServiceException(ResponseCode.ERR_UPDATE,"更改密码失败");
    }
        /*@Override
        public void sendEmail(int userId) {
            User user = userDao.selectById(userId);

            //通过用户id查找到用户并通过用户查找其登录账户里的邮箱信息
            String email = loginAccountDao.selectById(userDao.selectById(userId).getLoginAccountId()).getEmail();
            if (email == null) {
                throw new UserException(States.ERR_USER_NOT_FOUND.getStates(), "邮箱未绑定");
            }
            //获取发送的验证码
            String code = util.sendValidEMail(email);
            validationDao.updateById(validationDao.selectById(user.getValidationId()).setEmailCode(code));
        }*/

    @Override
    public void sendSms(int userId) {
        User user = userDao.selectById(userId);

        //通过用户id查找到用户并通过用户查找其登录账户里的邮箱信息
        String phone = loginAccountDao.selectById(user.getUserId()).getPhone();
        if (phone == null) {
            throw new UserException(ResponseCode.ERR_USER_NOT_FOUND.getValue(), "用户不存在");
        }

        //获取发送的验证码
        String code = util.sendValidSms(phone);
        validationDao.updateById(validationDao.selectById(user.getUserId()).setPhoneCode(code));
    }
}
